package handler

import (
	"context"
	"fmt"
	"github.com/duanshanghanqing/pistol"
	pb "goods-srv/gen/user"
	"goods-srv/internal/dao"
	"goods-srv/internal/model"
	"goods-srv/libs"
	"google.golang.org/protobuf/types/known/emptypb"
	"io"
	"time"
)

type userServer struct {
	pb.UnimplementedUserServer
}

//func convertTimestampToTime(timestamp *timestamppb.Timestamp) *time.Time {
//	if timestamp == nil {
//		return nil
//	}
//	t := timestamp.AsTime()
//	return &t
//}
//
//func convertTimeToTimestamp(t *time.Time) *timestamppb.Timestamp {
//	return &timestamppb.Timestamp{Seconds: t.Unix(), Nanos: int32(t.Nanosecond())}
//}

func (s *userServer) CreateUser(_ context.Context, createUserMessage *pb.CreateUserMessage) (*emptypb.Empty, error) {
	empty := &emptypb.Empty{}
	if err := createUserMessage.Validate(); err != nil {
		return empty, err
	}
	userModel := model.User{}
	libs.MappingStruct(createUserMessage, &userModel)
	fmt.Println(userModel.Birthday)
	//userModel.Birthday = convertTimestampToTime(createUserMessage.Birthday)
	_, err := dao.CreateUser(userModel)
	if err != nil {
		return empty, err
	}
	return empty, nil
}

func (s *userServer) DeleteUser(_ context.Context, deleteUserMessage *pb.DeleteUserMessage) (*emptypb.Empty, error) {
	empty := &emptypb.Empty{}
	if err := deleteUserMessage.Validate(); err != nil {
		return empty, err
	}
	userModel := model.User{}
	libs.MappingStruct(deleteUserMessage, &userModel)
	if err := dao.DeleteUser(userModel.Id); err != nil {
		return empty, err
	}
	return empty, nil
}

func (s *userServer) UpdateUser(_ context.Context, updateUserMessage *pb.UpdateUserMessage) (*emptypb.Empty, error) {
	empty := &emptypb.Empty{}
	if err := updateUserMessage.Validate(); err != nil {
		return empty, err
	}
	userModel := model.User{}
	libs.MappingStruct(updateUserMessage, &userModel)
	if err := dao.UpdateUser(userModel); err != nil {
		return empty, err
	}
	return empty, nil
}

func (s *userServer) SelectUserById(_ context.Context, selectUserByIdMessage *pb.SelectUserByIdMessage) (*pb.UserMessage, error) {
	userMessage := pb.UserMessage{}
	if err := selectUserByIdMessage.Validate(); err != nil {
		return &userMessage, err
	}
	userModel := model.User{}
	libs.MappingStruct(selectUserByIdMessage, &userModel)
	newUserModel, err := dao.SelectUserById(userModel.Id)
	if err != nil {
		return nil, err
	}
	libs.MappingStruct(newUserModel, &userMessage)
	return &userMessage, nil
}

func (s *userServer) SelectUserByAccount(_ context.Context, selectUserByAccountMessage *pb.SelectUserByAccountMessage) (*pb.UserMessage, error) {
	userMessage := pb.UserMessage{}
	if err := selectUserByAccountMessage.Validate(); err != nil {
		return &userMessage, err
	}
	newUserModel, err := dao.SelectUserByAccount(selectUserByAccountMessage.Account)
	if err != nil {
		return nil, err
	}
	libs.MappingStruct(newUserModel, &userMessage)
	return &userMessage, nil
}

func (s *userServer) SelectUserByMobile(_ context.Context, selectUserByMobileMessage *pb.SelectUserByMobileMessage) (*pb.UserMessage, error) {
	userMessage := pb.UserMessage{}
	if err := selectUserByMobileMessage.Validate(); err != nil {
		return &userMessage, err
	}
	newUserModel, err := dao.SelectUserByMobile(selectUserByMobileMessage.Mobile)
	if err != nil {
		return &userMessage, err
	}
	libs.MappingStruct(newUserModel, &userMessage)
	return &userMessage, nil
}

func (s *userServer) CheckUserPassword(_ context.Context, checkUserPasswordMessage *pb.CheckUserPasswordMessage) (*pb.CheckUserPasswordMessage, error) {
	if err := checkUserPasswordMessage.Validate(); err != nil {
		return checkUserPasswordMessage, err
	}
	userModel := model.User{}
	libs.MappingStruct(checkUserPasswordMessage, &userModel)
	newUserModel, err := dao.SelectUserById(userModel.Id)
	if err != nil {
		return checkUserPasswordMessage, err
	}
	checkUserPasswordMessage.Result = libs.GetSha256(checkUserPasswordMessage.Password) == newUserModel.Password
	return checkUserPasswordMessage, nil
}

func (s *userServer) SelectUserList(context.Context, *emptypb.Empty) (*pb.UserListMessage, error) {
	userModelList, err := dao.SelectUserList()
	if err != nil {
		return nil, err
	}
	userListMessage := pb.UserListMessage{}
	for _, v := range userModelList {
		userMessage := pb.UserMessage{}
		libs.MappingStruct(v, &userMessage)
		userListMessage.List = append(userListMessage.List, &userMessage)
	}
	return &userListMessage, nil
}

func (s *userServer) SelectUserPageList(_ context.Context, userPageQueryMessage *pb.UserPageQueryMessage) (*pb.UserPageQueryMessage, error) {
	// 把 grpc 客户端传来的分页信息，映射到 dao 层分页结构体上
	// 1.初始化dao 层分页查询结构体
	daoPageQuery := dao.NewPageQuery()

	// 2.映射分页信息
	libs.MappingStruct(userPageQueryMessage.Page, &daoPageQuery.Page)
	userModel := model.User{}
	libs.MappingStruct(userPageQueryMessage.Query, &userModel)
	daoPageQuery.Query = userModel

	// 3.执行查询
	list, err := dao.SelectUserPageList(daoPageQuery)
	if err != nil {
		return nil, err
	}

	// 4.查询结果映射返回
	pageMessage := pistol.PageMessage{}
	libs.MappingStruct(daoPageQuery.Page, &pageMessage)
	userPageQueryMessage.Page = &pageMessage
	for _, v := range list {
		userMessage := pb.UserMessage{}
		libs.MappingStruct(v, &userMessage)
		userPageQueryMessage.List = append(userPageQueryMessage.List, &userMessage)
	}

	return userPageQueryMessage, nil
}

// SelectUserListByServerStream 视频地址:https://www.bilibili.com/video/BV1GE411A7kp/?p=19&spm_id_from=333.1007.top_right_bar_window_history.content.click
// 流相关文档: https://colobu.com/2017/04/06/dive-into-gRPC-streaming/
// 服务端向客户端发送流
func (s *userServer) SelectUserListByServerStream(_ *emptypb.Empty, stream pb.User_SelectUserListByServerStreamServer) error {
	userModelList, err := dao.SelectUserList()
	if err != nil {
		return err
	}
	userModelList = append(userModelList, userModelList[0], userModelList[0], userModelList[0], userModelList[0], userModelList[0], userModelList[0])

	userListMessage := pb.UserListMessage{}
	for _, v := range userModelList {
		userMessage := pb.UserMessage{}
		libs.MappingStruct(v, &userMessage)
		userListMessage.List = append(userListMessage.List, &userMessage)
		time.Sleep(time.Second * 2) // 模拟很慢，每隔2秒发送一次
		err = stream.Send(&userListMessage)
		if err != nil {
			return err
		}
	}
	return nil
}

// SelectUserListByClientStream 服务端接收客户端发送的流
func (s *userServer) SelectUserListByClientStream(stream pb.User_SelectUserListByClientStreamServer) error {
	var userListMessage *pb.UserListMessage
	for {
		req, err := stream.Recv()
		if err == io.EOF { // 接收完了
			return stream.SendAndClose(userListMessage) // 把接收的数据返回给客户端，并关闭流
		}
		if err != nil {
			fmt.Println(err.Error())
			return err
		}
		fmt.Println(req)
		userListMessage = req
	}
}

// SelectUserListByClientServerStream 双向流
func (s *userServer) SelectUserListByClientServerStream(stream pb.User_SelectUserListByClientServerStreamServer) error {
	// 接收客户端数据
	for {
		req, err := stream.Recv()
		if err == io.EOF { // 接收完了
			return nil // 双向流，不存在能接收完
		}
		if err != nil {
			fmt.Println("1", err.Error())
			return err
		}
		fmt.Println(req)

		// 向客户端发送数据
		err = stream.Send(req)
		if err != nil {
			fmt.Println("2", err.Error()) // 继续接收，不理会错误
		}
	}
}

func NewUserService() pb.UserServer {
	return &userServer{}
}
